package com.rt.cloud.auth.config.login;

import com.rt.cloud.auth.config.MyUserDetailServiceImpl;
import com.rt.cloud.auth.config.exception.PasswordException;
import com.rt.cloud.auth.controller.captchaSlide.VerifyImageController;
import com.rt.cloud.auth.facade.UserApi;
import com.rt.easyjava.common.base.Result;
import com.rt.easyjava.common.rsa.RSAUtils;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Map;

/**
 * https://github.com/mingyang66/spring-parent/blob/master/spring-security-oauth2-server-redis-service/event.md
 * @Description: 用户自定义身份认证
 * @ProjectName: spring-parent
 * @Package: com.yaomy.security.provider.MyAuthenticationProvider
 * @Date: 2019/7/2 17:17
 * @Version: 1.0
 */
@Component(value = "userAuthenticationProvider")
public class UserAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private MyUserDetailServiceImpl myUserDetailService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private ApplicationEventPublisher publisher;
    @Autowired
    private VerifyImageController verifyImageController;
    @Resource
    UserApi userApi;

    // 用户登录信息 rsa private key
    private static String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKyhiFP/B754uArs\n" +
            "kFBzUzWQgYK4Z5bJd8z2m8XfL/MN4Z6W/LbuwN2IHF9bxn4LM0dCg1Vseo7IdoPw\n" +
            "sF9EMit88EeCWkNH12ds08DrS6Y/3ZChNGqWRf5GPPNJG0+ZLDeXKBiFvgpUhZFD\n" +
            "S2PseGOPdbK4Dflt46uXE1xg4mtDAgMBAAECgYEAob8z+eehfOClKG8ghJCZrT15\n" +
            "a16WiJy6KAwERjDpP2WJOUuk+03W3XpzgxF9eInMAP+cCIT8jB3dlaAF0S0Xh0cr\n" +
            "Awxr0iT2rpkP2gUzr3ME8iSyDzQXnv+cqhpQBKei8TcCSSFM6bd0qhzAEBkoESqR\n" +
            "BEx6/Kisvd4n5nMkUXECQQDdk2w1XAAtoP3AEXtoCI85PzHX9GertfLijSeNM4x+\n" +
            "J9+r6EG0+B8mAgLXnhb7V1JgEwtfLtfFNSouhCrVUEB5AkEAx3N11TNU57SQznjX\n" +
            "hDsDBRUxAePJ12ksBhBeY3NESOP/F/KfrF9/bVb6g4gPI52WMyycaOEpReLe3cO7\n" +
            "wuHymwJATYgMUQ+EMHMo11BGsjxsgUePlVU8AWWFO6jQsiPbgTlKlsiKVVyM6avC\n" +
            "etgiiogfluaTEBdAAQ19WRF+O239YQJBAJ0ctaB5bBONqFgM1vBBsBJL7Cvp7PBz\n" +
            "14r7T+8VOKAWgbayl9cn7vAJiRMdlZdfppavOJJhc6qqmRal/fz5EasCQGy+5GAB\n" +
            "LFjSNkRXMMEX0QDOWz3MFIWYCqlCdtsjcJBU4/GBb/FPyElvXJg26pVvz46JhpfQ\n" +
            "Rw32zgNDUO16W+4=";
    /**
     * @Description 认证处理，返回一个Authentication的实现类则代表认证成功，返回null则代表认证失败
     * @Date 2019/7/5 15:19
     * @Version  1.0
     */
    @SneakyThrows
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        System.out.println("===== authentication:" +authentication.getDetails());
        // image code verify
        Map detailsMap = (Map)authentication.getDetails();
        /*
        滑动验证图片
        String grant_type = (String) detailsMap.get("grant_type");
        String platform = (String) detailsMap.get("platform");
        String imageCode = (String) detailsMap.get("imageCode");
        String distance = (String) detailsMap.get("distance");
        String slideUuid = (String) detailsMap.get("slideUuid");*/
        String loginInfoEncode = (String) detailsMap.get("loginInfoEncode");
        // 内部调用 SSO
        String request_from = (String) detailsMap.get("request_from");
        if ("innerService".equalsIgnoreCase(request_from))
        {
            String username = (String) detailsMap.get("username");
            String pswd = (String) detailsMap.get("pswd");

            if (StringUtils.isBlank(username) || StringUtils.isBlank(pswd)) {
                throw new RuntimeException("内部验证失败");
            }

            UserDetails user = myUserDetailService.loadUserByUsername(username);
            if (!pswd.equalsIgnoreCase(user.getPassword())) {
                throw new RuntimeException("内部验证密码错误");
            }
            //获取用户权限信息
            Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
            return new UsernamePasswordAuthenticationToken(user, pswd, authorities);
        }

        /*Result result1 = verifyImageController.checkCaptchaImg(distance,slideUuid);
        if (!result1.isSuccess()){
            throw new PasswordException(result1.getContent());
        }*/

        // 当loginname and password 加密了，要加密的数据，解密填充
        byte[] mingByte = RSAUtils.decryptByPrivateKey(Base64.decodeBase64(loginInfoEncode),privateKey);
        String loginInfo = new String(mingByte, "utf-8");
        String[] loginInfoArr = loginInfo.split("_@#!#@_");
        if (loginInfoArr.length!=4) {
            throw new PasswordException("用户登录信息有错误");
        }
        String username = loginInfoArr[0];
        String password = loginInfoArr[1];
        String loginTimes = loginInfoArr[2];
        String time = loginInfoArr[3];

        if(StringUtils.isBlank(username)){
            throw new PasswordException("用户名不可以为空");
        }
        if(StringUtils.isBlank(password)){
            throw new PasswordException("密码不可以为空");
        }
        //获取用户信息
        UserDetails user = myUserDetailService.loadUserByUsername(username);
        if (user==null) {
            throw new PasswordException(username+"：用户不存在");
        }

        Result result2 = userApi.validatePassword(username, password,  user.getPassword(), loginTimes);
        if (!result2.isSuccess()) {
            throw new PasswordException(result2.getContentOnly());
        }

        //获取用户权限信息
        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();

        return new UsernamePasswordAuthenticationToken(user, password, authorities);
    }

    /**
     * @Description 如果该AuthenticationProvider支持传入的Authentication对象，则返回true
     * @Date 2019/7/5 15:18
     * @Version  1.0
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return aClass.equals(UsernamePasswordAuthenticationToken.class);
    }


}
